package com.wonder.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.PeekingIterator;
import com.google.common.util.concurrent.ForwardingFuture;
import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.utils.VtuzxUtil;
import com.wonder.admin.service.IVtuzxKingdeeService;
import com.wonder.admin.service.impl.VtuzxKingdeeServiceImpl;
import com.wonder.app.domain.SfcOptrpt;
import com.wonder.app.domain.SfcOptrptPackage;
import com.wonder.app.domain.SfcProplan;
import com.wonder.app.domain.SyncOrderDetail;
import com.wonder.app.mapper.SfcOprptPackageDao;
import com.wonder.app.mapper.SfcProplanDao;
import com.wonder.app.request.SfcOptrptPackageRequest;
import com.wonder.app.service.*;
import com.wonder.common.utils.DateUtils;
import com.wonder.constant.BillNoGenerator;
import com.wonder.constant.BillType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.aggregation.FacetOperation;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class SfcOptrptPackageServiceImpl extends ServiceImpl<SfcOprptPackageDao, SfcOptrptPackage> implements SfcOptrptPackageService {
    private static final Logger _logger = LoggerFactory.getLogger(SfcOptrptPackageServiceImpl.class);

    @Autowired
    private SfcOptrptPackageService sfcOptrptPackageService;

    @Autowired
    private SfcProplanService sfcProplanService;

    @Autowired
    private SfcProplanDao sfcProplanDao;

    @Autowired
    private SfcOprptPackageDao sfcOprptPackageDao;

    @Autowired
    private SyncKingdeeOrderService syncKingdeeOrderService;

    @Autowired
    private PrdInstockService prdInstockService;

    @Autowired
    private PrdPickService prdPickService;

    @Autowired
    private PrdFeedService prdFeedService;

    @Autowired
    private PrdReturnService prdReturnService;

    @Autowired
    private SyncOrderService syncOrderService;

    @Autowired
    private IVtuzxKingdeeService vtuzxKingdeeService;

    @Override
    public IPage<SfcOptrptPackage> packageList(SfcOptrptPackageRequest request, Page<SfcOptrptPackage> page) {
        LambdaQueryWrapper<SfcOptrptPackage> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        if (request.getBillNo() != null){
            lambdaQueryWrapper.like(SfcOptrptPackage::getBillNo,request.getBillNo());
        }

        if (request.getMoBillNo() != null){
            lambdaQueryWrapper.like(SfcOptrptPackage::getMoBillNo,request.getMoBillNo());
        }

        if (request.getStatus() != null){
            lambdaQueryWrapper.like(SfcOptrptPackage::getStatus,request.getStatus());
        }


        if (request.getCreateTime() != null){
            Date[] orderDate = request.getCreateTime();
            if(orderDate.length>0)
                lambdaQueryWrapper.ge(SfcOptrptPackage::getCreateTime, orderDate[0]);
            if(orderDate.length==2)
                lambdaQueryWrapper.le(SfcOptrptPackage::getCreateTime,orderDate[1]);
        }
        lambdaQueryWrapper.orderByDesc(SfcOptrptPackage::getCreateTime);
        Page<SfcOptrptPackage> selectPage = this.baseMapper.selectPage(page, lambdaQueryWrapper);
        return selectPage;

    }

    @Override
    public Boolean importReport(String userName, Long user_id, List<Map<String, Object>> map) throws Exception {
        if(map==null || map.size()==0) {
            throw new RuntimeException("没有获取到数据,请检查模版sheet页");
        }
        List<String> moNoList = new ArrayList<>();//存生产订单号
        List<SfcOptrptPackage> packageList = new ArrayList<>();
        int i = 2;//行号
        for (Map<String,Object> data : map){
            String moBillNo = VtuzxUtil.getString(data,"生产订单编号");//生产订单编号
            String itemNo = VtuzxUtil.getString(data,"件号");//件号
            String materialNo = VtuzxUtil.getString(data,"物料编码");//物料编码
            double quaQty = VtuzxUtil.getDouble(data,"合格数量");//合格数量
            double failQty = VtuzxUtil.getDouble(data,"不合格数量");//不合格数量
            Integer fDate = VtuzxUtil.getInt(data,"日期");

            SfcOptrptPackage sfcOptrptPackage = new SfcOptrptPackage();
            String billNo = BillNoGenerator.createBillNo(BillType.GXHB);
            sfcOptrptPackage.setBillNo(billNo);
            sfcOptrptPackage.setMoBillNo(moBillNo);
            sfcOptrptPackage.setMaterialNo(materialNo);
            sfcOptrptPackage.setSpecification(itemNo);
            sfcOptrptPackage.setStatus("save");
            sfcOptrptPackage.setQuaQty(quaQty);
            sfcOptrptPackage.setFailQty(failQty);
            sfcOptrptPackage.setLine(i);//行号
            sfcOptrptPackage.setCreateTime(new Date());
            sfcOptrptPackage.setWorkShopName("包装车间");
            sfcOptrptPackage.setWorkShopNo("BZ");
            sfcOptrptPackage.setCreateUserName(userName);
            sfcOptrptPackage.setKingdeePickNo("");
            sfcOptrptPackage.setKingdeeReport("");
            sfcOptrptPackage.setKingdeeInNo("");
            sfcOptrptPackage.setKingdeeFeedNo("");
            sfcOptrptPackage.setKingdeeReturn("");
            sfcOptrptPackage.setFDate(DateUtils.conVerDate(fDate));
            packageList.add(sfcOptrptPackage);
            if (!moNoList.contains(moBillNo)){
                moNoList.add(moBillNo);
            }
            i++;
        }
        Map<String,Object> moMap = new HashMap<>();//key；订单 val:工序号
        //查询出工序计划
        List<SfcProplan> planList = sfcProplanDao.selectList(new LambdaQueryWrapper<SfcProplan>()
                .in(SfcProplan::getMoBillNo, moNoList));
        for (SfcProplan sfcProplan : planList){
            String moBillNo = sfcProplan.getMoBillNo();
            String billNo = sfcProplan.getBillNo();//工序号
            moMap.put(moBillNo,billNo);
        }
        List<SfcOptrptPackage> newPackageList = new ArrayList<>();
        for (SfcOptrptPackage sfcOptrptPackage : packageList){
            String planNo = VtuzxUtil.getString(moMap,sfcOptrptPackage.getMoBillNo());
            sfcOptrptPackage.setPlanNo(planNo);

        }
        //进行数据校验,判断库存和单据状态是否都是开工
        Boolean aBoolean = checkReportExcel(userName, user_id, packageList);
        if (!aBoolean){
            throw new RuntimeException("模板数据校验未通过,请查看传单日志查看具体信息");
        }


        boolean b = sfcOptrptPackageService.saveOrUpdateBatch(packageList);
        for (SfcOptrptPackage sfcOptrptPackage : packageList){
            try {
                auditReportPackage(sfcOptrptPackage,userName,user_id);
                sfcOptrptPackage.setStatus("audit");
                newPackageList.add(sfcOptrptPackage);
            } catch (Exception e){
                _logger.info(e.getMessage());
            }

        }
        boolean res = sfcOptrptPackageService.saveOrUpdateBatch(newPackageList);
        return true;
    }

    /**
     * 修改包装汇报信息
     * @param map
     * @param userName
     * @param user_id
     * @return
     * @throws Exception
     */
    @Override
    public Boolean updatePackage(Map<String, Object> map, String userName, Long user_id) throws Exception {
        String billNo = VtuzxUtil.getString(map,"billNo");
        SfcOptrptPackage sfcOptrptPackage = this.baseMapper.selectOne(new LambdaQueryWrapper<SfcOptrptPackage>()
                .eq(SfcOptrptPackage::getBillNo, billNo));
        String status = sfcOptrptPackage.getStatus();
        if ("audit".equals(status)){
            throw new RuntimeException("单据已审核无法修改");
        }
        double outFailQty = VtuzxUtil.getDouble(map,"outFailQty");//外协不良
        double returnQty = VtuzxUtil.getDouble(map,"returnQty");//返修
//        sfcOptrptPackage.setOutFailQty(outFailQty);
//        sfcOptrptPackage.setReturnQty(returnQty);
        boolean b = sfcOptrptPackageService.saveOrUpdate(sfcOptrptPackage);

        return b;
    }

    /**
     * 审核包装汇报
     * @param userName
     * @param user_id
     * @return
     * @throws Exception
     */
    @Override
    public Boolean auditReportPackage(SfcOptrptPackage sfcOptrptPackage, String userName, Long user_id) throws Exception {
        //合格数量对应生产入库单，仓库=出货成品仓，领料单，仓库=包装材料库
        //报废数量对应生产退料单,仓库=回材库，生产补料单，仓库=包装材料库单据是保存状态

        try {
            //先传领料
            prdPickService.createPickBillPackage(user_id,userName,sfcOptrptPackage);
            //传汇报
            syncKingdeeOrderService.syncPrdReportBao(user_id,sfcOptrptPackage,null);
            //传入库
            prdInstockService.createPrdInstockPackage(user_id,userName,sfcOptrptPackage);
            //废料数量传补料和退料
            if (sfcOptrptPackage.getFailQty() > 0){
                String kingdeeFeedNo = prdFeedService.createFeedBillPackage(user_id, userName,sfcOptrptPackage,"fail");//返回补料单号
                prdReturnService.createReturnBillPackage(user_id, userName,sfcOptrptPackage,"fail",kingdeeFeedNo);
            }
        } catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }
        return true;
    }


    /**
     * 校验销售订单导入的数据
     * @param user_id
     * @param
     * @return
     * @throws Exception
     */
    private Boolean checkReportExcel(String userName,Long user_id,List<SfcOptrptPackage> newPackageList) throws Exception{
        String tbbillNo = syncOrderService.startSyncOrder(userName,user_id,"包装汇报模板级校验");
        Map<String,Object> inventoryMap = new HashMap<>();//key:物料编码 val:数量
        Map<String,Object> lineMap = new HashMap<>();//key:物料编码 val:行号 如果物料编码相同，出现问题会提示最后一个行号
        Map<String,Object> materialMap = new HashMap<>();//key :物料编码 val:件号
        List<String> moNoList = new ArrayList<>();//生产订单集合
        List<String> materialNoList = new ArrayList<>();
        for (SfcOptrptPackage data : newPackageList){
            String moBillNo = data.getMoBillNo();
            String materialNo = data.getMaterialNo();
            String specification = data.getSpecification();//件号
            Date fDate = data.getFDate();
            Integer line = data.getLine();
            Double failQty = data.getFailQty();
            Double quaQty = data.getQuaQty();
            if (!materialNoList.contains(materialNo)){
                materialNoList.add(materialNo);
            }
            if(!moNoList.contains(moBillNo)){
                moNoList.add(moBillNo);
            }
            double mapCount = VtuzxUtil.getDouble(inventoryMap,materialNo);

            inventoryMap.put(materialNo,quaQty + failQty + mapCount);
            materialMap.put(materialNo,specification);
            lineMap.put(materialNo,line);

        }
        List<SyncOrderDetail> orderDetailList = new ArrayList<>();
        //查询金蝶即时库存
        Map<String, Object> queryMap = vtuzxKingdeeService.getInventoryBymaterialList(user_id,materialNoList);
        for (Map.Entry<String, Object> entry : queryMap.entrySet()) {
            String materialNo = entry.getKey();//物料编码
            Double inventoryCount = (Double) entry.getValue();//库存数量
            double importCount = VtuzxUtil.getDouble(inventoryMap,materialNo);//需要导入的数量
            if (inventoryCount < importCount){
                String specification = VtuzxUtil.getString(materialMap,materialNo);
                Integer line = VtuzxUtil.getInt(lineMap,materialNo);
                SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
                syncOrderDetail.setOrderNo("包装汇报模板级校验");//客户订单号
                syncOrderDetail.setBillNo(tbbillNo);
                syncOrderDetail.setCreateTime(new Date());
                syncOrderDetail.setUpdateTime(new Date());
                syncOrderDetail.setIsSuccess(false);
                syncOrderDetail.setMessage("第" + line + "行"+ specification +"领料库存不足,缺少" + (importCount - inventoryCount));
                orderDetailList.add(syncOrderDetail);
            }
        }


        List<Integer> statusList = new ArrayList<>(Arrays.asList(3, 4, 5));
        //查询金蝶单据状态,判断工序计划状态是已审核，分录状态为下达3，开工4，完工5
        //查询金蝶即时库存
        //需要校工序计划上的工序数量不能大于订单数量
        Map<String, Object> moQtyMap = vtuzxKingdeeService.getMoQty(user_id,moNoList);//key生产订单 val:订单数量
        Map<String, Object> orderMap = vtuzxKingdeeService.getOrderStatus(user_id,moNoList);//key生产订单 val:单据状态(map)
        for (SfcOptrptPackage data : newPackageList){
            Integer line = data.getLine();
            String moBillNo = data.getMoBillNo();
            Map<String,Object> statusMap = VtuzxUtil.getObject(orderMap,moBillNo);
            if (!VtuzxUtil.isEmpty(statusMap)){
                String FDocumentStatus = VtuzxUtil.getString(statusMap,"FDocumentStatus");//单据状态
                int FOperStatus = VtuzxUtil.getInt(statusMap,"FOperStatus");//分录状态
                double planQty = VtuzxUtil.getDouble(statusMap,"FOperQty");//计划数量
                double moQty = VtuzxUtil.getDouble(moQtyMap,moBillNo);//订单数量
                if(!"C".equals(FDocumentStatus) || !statusList.contains(FOperStatus)){//单据状态是已审核
                    SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
                    syncOrderDetail.setOrderNo("包装汇报模板级校验");//客户订单号
                    syncOrderDetail.setBillNo(tbbillNo);
                    syncOrderDetail.setCreateTime(new Date());
                    syncOrderDetail.setUpdateTime(new Date());
                    syncOrderDetail.setIsSuccess(false);
                    syncOrderDetail.setMessage("第" + line + "行的单据状态需要是已审核,并且分录状态为下达,开工,或完工");
                    orderDetailList.add(syncOrderDetail);
                }
                if(planQty > moQty){
                    SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
                    syncOrderDetail.setOrderNo("包装汇报模板级校验");//客户订单号
                    syncOrderDetail.setBillNo(tbbillNo);
                    syncOrderDetail.setCreateTime(new Date());
                    syncOrderDetail.setUpdateTime(new Date());
                    syncOrderDetail.setIsSuccess(false);
                    syncOrderDetail.setMessage("第" + line + "工序计划数量大于订单数量");
                    orderDetailList.add(syncOrderDetail);
                }
            } else {
                SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
                syncOrderDetail.setOrderNo("包装汇报模板级校验");//客户订单号
                syncOrderDetail.setBillNo(tbbillNo);
                syncOrderDetail.setCreateTime(new Date());
                syncOrderDetail.setUpdateTime(new Date());
                syncOrderDetail.setIsSuccess(false);
                syncOrderDetail.setMessage("第" + line + "行生产订单不存在");
                orderDetailList.add(syncOrderDetail);
            }

        }


        syncOrderService.endSyncOrder(orderDetailList,tbbillNo);
        if(!VtuzxUtil.isEmpty(orderDetailList)){
            return false;
        } else {
            return true;
        }
    }
}
